<template>
  <BasicModal
    title="测试窗口"
    :visible="visible"
    :mask="false"
    :width="680"
    :minHeight="300"
    :maskClosable="false"
    :canFullscreen="false"
    @cancel="handleCancel"
    cancelText="关闭"
    wrapClassName="test-modal"
  >
    <div class="test-window">
      <section class="output-container" v-if="output">
        <a-tabs size="small">
          <a-tab-pane :tab="values.outputTitle" v-for="(values, index) in outputContents" :key="index + 'title'">
            <div :class="values.outputName.length > 0 ? 'log-container' : ''" :style="{ height: hiddenLog ? '300px' : '' }">
              <div
                class="row"
                :style="{ width: `${220 * values.outputName.length <= 660 ? 220 * values.outputName.length : 120 * values.outputName.length}px` }"
              >
                <span
                  :style="{ width: `${220 * values.outputName.length <= 660 ? 220 : 120}px` }"
                  v-for="(item, index) in values.outputName"
                  :key="index + 'c'"
                  class="table_body"> 
                  {{ item }} 
                </span>
              </div>

              <div v-if="result">
                <div
                  class="row"
                  :style="{
                    width: `${220 * values.messageTable.length <= 660 ? 220 * values.messageTable.length : 120 * values.messageTable.length}px`,
                  }"
                >
                  <div
                    class="table_body"
                    :style="{ width: `${220 * values.messageTable.length <= 660 ? 220 : 120}px` }"
                    v-for="(i, index) in values.messageTable"
                    :key="index + 'x'"
                  >
                    <a-tooltip placement="bottomLeft" trigger="click">
                      <template #title>
                        <span>{{ i }}</span>
                      </template>
                      {{ i }}
                    </a-tooltip>
                  </div>
                </div>
              </div>
              <div v-else>
                <div
                  v-for="(i, index) in values.messageTable"
                  :key="index"
                  class="row"
                  :style="{ width: `${220 * i.length <= 660 ? 220 * i.length : 120 * i.length}px` }"
                >
                  <div class="table_body" :style="{ width: `${220 * i.length <= 660 ? 220 : 120}px` }" v-for="(item, index) in i" :key="index + 'x'">
                    <a-tooltip placement="bottomLeft" trigger="click">
                      <template #title>
                        <span>{{ item }}</span>
                      </template>
                      <span>{{ item }}</span>
                    </a-tooltip>
                  </div>
                </div>
              </div>
            </div>
          </a-tab-pane>
        </a-tabs>
      </section>
      <section class="log-container log-container-font" v-if="log" :style="{ height: hiddenTable ? '320px' : '100px' }" ref="logContainer">
        <div v-for="(item, index) in messageNewLog" :key="index + 'log'">
          <span
            v-for="(i, index) in item.slice(0, item.length - 1)"
            :key="index + 's'"
            :style="{ color: index == 3 ? item[item.length - 1] : '#000' }"
            class="defaultOneLog"
          >
            <span v-if="index !== item.length - 1">
              <a-tooltip placement="topLeft" trigger="click" overlayClassName="tooltip_class">
                <template #title>
                  <span>{{ i }}</span>
                </template>
                {{ i }}
              </a-tooltip>
            </span>
          </span>
        </div>
      </section>
      <ul class="debug-container" v-if="debuger">
        <li><label>调试单元：</label>{{ cell.value }}</li>
        <li><label>调试参数：</label>{{ messageDebugs.key }}</li>
        <li>
          <label>调试值：</label>
          <vue-json-pretty v-if="isJsonMsg" :path="'res'" :deep="2" :data="messageDebugs ? messageDebugs.value : ''" />
          <span v-else>{{ messageDebugs ? messageDebugs.value : '' }}</span>
        </li>
      </ul>
    </div>

    <template #footer>
      <a-button size="small" type="primary" @click="handleCancel">关闭</a-button>
      <a-button size="small" @click="handleOutput">显示/隐藏输出</a-button>
      <a-button size="small" @click="handleLog">显示/隐藏日志</a-button>
      <a-button size="small" @click="handleConnect">{{ connectStatus }}</a-button>
      <a-input size="small" placeholder="输入关键字过滤日志" class="searchInput" v-model:value="keyLogWord" />
    </template>
  </BasicModal>
</template>
<script setup>
  import { ref, reactive, watch, computed, nextTick } from 'vue';
  import { useGlobSetting } from '/@/hooks/setting';
  import { getToken } from '/@/utils/auth';
  import { BasicModal } from '/@/components/Modal';
  import { RpaEditor } from '../utils/render/index';
  import VueJsonPretty from 'vue-json-pretty';
  const props = defineProps({
    cell: { type: Object },
    editor: { type: RpaEditor },
  });
  const emit = defineEmits(['handleShowBtn', 'debugMessage']);
  const glob = useGlobSetting();
  const visible = ref(false);
  const websock = ref();
  const logContainer = ref(null);
  const debugs = ref('');
  const output = ref(true);
  const log = ref(false);
  const outputContents = reactive([]);
  const messageLog = ref([]);
  const hiddenTable = ref(false);
  const hiddenLog = ref(false);
  const connectStatus = ref('停止');
  const keyLogWord = ref('');
  const messageTable = reactive([]);
  const nodeIds = reactive([]);
  const result = ref(false);
  const messageDebugs = ref('');
  const debuger = ref(false);

  const isJsonMsg = computed(() => {
    return Array.isArray(messageDebugs.value.value) || typeof messageDebugs.value.value === 'object';
  });

  function testAction(debug) {
    visible.value = true;
    debugs.value = debug;
    outputContents.splice(0, outputContents.length);
    initWebSocket();
  }

  watch(
    () => messageLog.value,
    () => {
      nextTick(() => {
        if (log.value && logContainer.value) {
          logContainer.value.scrollTop = logContainer.value.scrollHeight;
        }
      });
    },
    { deep: true }
  );

  const messageNewLog = computed(() => {
    if (!keyLogWord.value) {
      return messageLog.value;
    } else {
      return messageLog.value.filter((item) => {
        return item.some((value) => {
          return String(value).indexOf(keyLogWord.value) > -1;
        });
      });
    }
  });
  function initWebSocket() {
    const token = getToken() || '';
    let url = glob.domainUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/ws-rpa/ws';
    websock.value = new WebSocket(url, [token]);
    websock.value.onopen = websocketOnopen;
    websock.value.onerror = websocketOnerror;
    websock.value.onmessage = websocketOnmessage;
    websock.value.onclose = websocketOnclose;
  }
  function websocketOnopen() {
    if (websock.value.readyState === 1) {
      websock.value.send(
        JSON.stringify({
          type: 'spider-flow',
          eventType: debugs.value === 'true' ? 'debug' : 'test',
          message: props.editor.getGraph().outPutXml(),
        })
      );
    }
  }
  function websocketOnmessage(e) {
    var event = JSON.parse(e.data);
    var { eventType, message } = event;
    var colors = {
      array: '#2a00ff',
      object: '#2a00ff',
      boolean: '#600100',
      number: '#000E59',
    };
    if (eventType === 'finish') {
      connectStatus.value = '重新开始';
      emit('handleShowBtn');
    } else if (eventType === 'output') {
      const { nodeId, outputNames, values } = message;
      output.value = true;
      var tableId = 'output-' + nodeId;
      var outputTitle = '输出-' + tableId;
      var cell = props.editor.getGraph().getCell(nodeId);
      if (cell) {
        outputTitle = cell.value;
      }
      var messageList = [];
      outputNames.forEach((item, index) => {
        var displayText = values[index];
        var variableType = Array.isArray(displayText) ? 'array' : typeof displayText;
        if (Array.isArray(displayText) || variableType === 'object') {
          displayText = JSON.stringify(displayText);
        }
        messageList.push(displayText);
      });
      messageTable.push(messageList);
      var nodeArr = [];
      nodeIds.push({ nodeId: nodeId });
      nodeIds.forEach((item) => {
        nodeArr.push(item.nodeId);
      });
      var _newArr = isEqual(nodeArr); // 筛选数组中重复出现的nodeId值及次数
      _newArr.forEach((item) => {
        if (item.count > 1) {
          result.value = false;
          if (_newArr.length === 1) {
            outputContents.length = 0; //数组置空
          }
        } else {
          result.value = true;
        }
      });
      var outputContent = {
        outputTitle: outputTitle,
        outputName: outputNames,
        messageTable: result.value ? messageList : messageTable,
      };
      outputContents.push(outputContent);
    } else if (eventType === 'log') {
      log.value = true;
      var texts = [];
      var defaultColor = message.level === 'error' ? 'red' : '';
      texts.push(message.level);
      texts.push(event.timestamp);
      var temp = message.message.split('{}');
      message.variables = message.variables || [];
      for (var j = 0, leng = temp.length; j < leng; j++) {
        if (temp[j] !== '') {
          texts.push(temp[j]);
        }
        var object = message.variables[j];
        if (object !== undefined) {
          var VariableType = '';
          var displayLogText = object;
          if (Array.isArray(object)) {
            VariableType = 'array';
            displayLogText = JSON.stringify(displayLogText);
          } else {
            VariableType = typeof object;
            if (VariableType === 'object') {
              displayLogText = JSON.stringify(displayLogText);
            }
          }
          texts.push(displayLogText);
        }
      }
      defaultColor = colors[VariableType] || '#025900';
      texts.push(defaultColor);
      messageLog.value.push(texts);
    } else if (eventType === 'debug') {
      props.editor.getGraph().setCellSelected(props.editor.getGraph().getCell(message.nodeId));
      emit('debugMessage', message);
      debuger.value = true;
      messageDebugs.value = message;
    }
  }
  function isEqual(array) {
    var res = [];
    for (var i = 0; i < array.length; ) {
      var count = 0;
      for (var j = i; j < array.length; j++) {
        if (array[i] === array[j]) {
          count++;
        }
      }
      res.push([array[i], count]);
      i += count;
    }
    var newArr = [];
    for (var z = 0; z < res.length; z++) {
      newArr.push({
        num: res[z][0],
        count: res[z][1],
      });
    }
    return newArr;
  }
  function websocketOnerror(e) {
    console.log(' WebSocket连接发生错误 ');
  }
  function websocketOnclose(e) {
    console.log('connection closed (' + e + ')');
  }
  function handleCancel() {
    visible.value = false;
    connectStatus.value = '停止';
    emit('handleShowBtn', false);
    output.value = false;
    log.value = false;
    debuger.value = false;
    hiddenTable.value = false;
    hiddenLog.value = false;
    emit('debugMessage', {});
    outputContents.splice(0, outputContents.length);
    messageTable.splice(0, messageTable.length);
    messageLog.value = [];
    keyLogWord.value = '';
    messageDebugs.value = '';
    try {
      websock.value.close();
    } catch {
      websock.value = null;
    }
  }
  function handleOutput() {
    output.value = !output.value;
    hiddenTable.value = !hiddenTable.value;
  }
  function handleLog() {
    log.value = !log.value;
    hiddenLog.value = !hiddenLog.value;
  }
  function handleConnect() {
    if (connectStatus.value === '停止') {
      websock.value.send(
        JSON.stringify({
          type: 'spider-flow',
          eventType: 'stop',
        })
      );
      debuger.value = false;
      messageDebugs.value = '';
      emit('debugMessage', {});
    } else {
      outputContents.splice(0, outputContents.length);
      messageTable.splice(0, messageTable.length);
      websock.value.send(
        JSON.stringify({
          type: 'spider-flow',
          eventType: debugs.value === 'true' ? 'debug' : 'test',
          message: props.editor.getGraph().outPutXml(),
        })
      );
      connectStatus.value = '停止';
    }
  }
  function handleNext() {
    websock.value.send(
      JSON.stringify({
        type: 'spider-flow',
        eventType: 'resume',
      })
    );
  }
  function handleStop() {
    websock.value.send(
      JSON.stringify({
        type: 'spider-flow',
        eventType: 'stop',
      })
    );
  }
  function handleClose() {
    handleCancel();
  }
  defineExpose({
    handleNext,
    handleStop,
    testAction,
    handleClose,
  });
</script>
<style lang="less">
  /* 测试、debuger模态框 ------ */
  .test-modal {
    pointer-events: none;
    user-select: none;
    .ant-modal {
      top: 150px;
      right: -400px;
    }
    ::-webkit-scrollbar {
      width: 0px;
      height: 0px;
      background-color: #f5f5f5;
    }
    /* 主题内容区 */
    // .ant-modal-body {
    //   padding: 0px 5px;
    .output-container {
      margin-bottom: 5px;
    }

    .output-title {
      width: 60px;
      padding: 5px 0;
      font-size: 14px;
      text-align: center;
      // border-bottom: solid 1px #1890FF;
    }

    .test-window {
      height: 340px;
      padding: 0px;
      overflow: hidden;
      position: relative;
      overflow: auto;
    }

    .row {
      overflow-x: auto;
      display: flex;
      align-items: center;
      border-bottom: solid 1px #ccc;
    }

    .table_body {
      height: 20px;
      line-height: 20px;
      display: inline-block;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      color: #000;
      padding: 0 10px;
      border-right: solid 1px #ccc;
    }

    .log-container {
      height: 200px;
      overflow: auto;
      font-weight: bold;
      font-size: 13px;
      font-family: Consolas;
      border: solid 1px #ccc;
      padding: 5px;
      margin-top: -16px;
    }

    .log-container-font {
      font-size: 14px;
      margin-top: 0px;
    }

    .defaultOneLog {
      margin-right: 10px;
      max-width: 43%;
      display: inline-block;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      color: #000;
    }
    // }

    .debug-container {
      padding: 5px;
      font-weight: bold;
      font-family: Consolas;
      font-size: 14px;
      color: #000;
      border: solid 1px #ccc;
      white-space: nowrap;
      margin: 5px 0;
      li {
        list-style: none;
        margin-bottom: 5px;
        label {
          width: 70px;
        }
      }
      li:nth-child(3) {
        display: flex;
        margin: 0;
        span {
          white-space: pre-wrap;
          word-break: break-all;
        }
      }
    }
  }
  .searchInput {
    width: 180px;
    margin-left: 10px;
  }
  .tooltip_class {
    max-width: 450px;
  }
</style>
